package vulcanus

import (
	managev1 "gitee.com/go-vulcanus/vulcanus/api/devmanage/v1"
	"gitee.com/go-vulcanus/vulcanus/connection"
	"gitee.com/go-vulcanus/vulcanus/transport"
	"github.com/tidwall/gjson"
)

const (
	ProtocolBinary   = 0
	ProtocolString   = 1
	DeviceConfigKey  = "DEVICE:CONFIG:"
	DeviceUpgradeKey = "DEVICE:UPGRADE:"
	DeviceSettingKey = "DEVICE:SETTING:"
)

// DeviceMsg 设备信息
type DeviceMsg struct {
	DeviceCode    string                    // 设备码
	Time          string                    // 时间
	Command       string                    // 指令类型
	SynInf        int64                     // 同步码
	DeviceType    string                    // 设备类型
	Protocol      int                       // 0.二进制 1.字符串
	Metadata      string                    // 原始数据
	Data          interface{}               // 解析后数据
	Attr          interface{}               // 附加属性
	DeviceConfig  *managev1.DeviceConfig    // 设备配置信息
	DeviceChannel *connection.DeviceChannel // 与客户端连接通道
}

type DeviceData struct {
	DeviceCode       string                   `json:"dcode"`
	SysCode          string                   `json:"sysCode"`
	DeviceType       string                   `json:"deviceType"`
	SensorConfigList []*managev1.SensorConfig `json:"sensorConfigList"`
	SensorDataList   []SensorData             `json:"sensorDataList"`
}

type SensorData struct {
	Time       string   `json:"time"`
	SystemTime string   `json:"systemTime"`
	DeviceTime string   `json:"deviceTime"`
	Data       []string `json:"data"`
}

type DeviceStateData struct {
	DeviceCode  string                  `json:"deviceCode"`
	SysCode     string                  `json:"sysCode"`
	DeviceType  string                  `json:"deviceType"`
	StateConfig []*managev1.StateConfig `json:"stateConfigList"`
	DataList    []StateData             `json:"dataList"`
}

type StateData struct {
	Time string   `json:"time"`
	Data []string `json:"data"`
}

func NewDeviceData(deviceConfig *managev1.DeviceConfig, sensorData *SensorData) *DeviceData {
	deviceData := &DeviceData{
		DeviceCode:       deviceConfig.DeviceCode,
		SysCode:          deviceConfig.SysCode,
		DeviceType:       deviceConfig.DeviceType,
		SensorConfigList: deviceConfig.SensorConfigList,
		SensorDataList:   []SensorData{*sensorData},
	}
	return deviceData
}

func NewDeviceStateData(deviceConfig *managev1.DeviceConfig, stateData *StateData) *DeviceStateData {
	deviceStateData := &DeviceStateData{
		DeviceCode:  deviceConfig.DeviceCode,
		SysCode:     deviceConfig.SysCode,
		DeviceType:  deviceConfig.DeviceType,
		StateConfig: deviceConfig.StateConfigList,
		DataList:    []StateData{*stateData},
	}
	return deviceStateData
}

type Metadata struct {
	DeviceCode string `json:"dcode"`
	Timestamp  int64  `json:"timestamp"`
	Type       string `json:"type"`
	Data       string `json:"data"`
}

type SensorDataEvent struct {
	Time         string
	Data         []string
	DeviceConfig *managev1.DeviceConfig
}

type ControlRespEvent struct {
	DeviceConfig *managev1.DeviceConfig
}

type MqttReplyEvent struct {
	Topic          string
	Content        string
	EncodedContent string
	DeviceConfig   *managev1.DeviceConfig
	DeviceChannel  *connection.DeviceChannel
	NeedReply      bool
}

type StateDataEvent struct {
	Time         string
	Data         []string
	DeviceConfig *managev1.DeviceConfig
}

type ControllerStateEvent struct {
	SwitchStatus []int16 // 开关状态
	Openings     []int16 // 开度
	Modes        []int16 // 控制模式
	DeviceConfig *managev1.DeviceConfig
}

type SocketSendEvent struct {
	Content      []byte
	DeviceConfig *managev1.DeviceConfig
}

type ControllerState struct {
	DeviceCode   string  `json:"dcode"`
	DeviceType   string  `json:"deviceType"`
	SwitchStatus []int16 `json:"switchStatus"`
	Openings     []int16 `json:"openings"`
	Modes        []int16 `json:"modes"`
}

// SettingParams 设备设置参数
type SettingParams struct {
	Uuid       string       `json:"uuid"`
	Time       string       `json:"time"`
	DeviceCode string       `json:"deviceCode"`
	Params     gjson.Result `json:"params"`
}

// SettingResult 设备设置参数结果
type SettingResult struct {
	SettingParams
	Success bool   `json:"success"`
	Message string `json:"message"`
}

// PictureData 图片数据
type PictureData struct {
	DeviceCode string `json:"deviceCode"`
	DeviceType string `json:"deviceType"`
	Time       string `json:"time"`
	Data       []byte `json:"data"`
}

type (
	MqttCodec interface {
		Decode(string, []byte) (*DeviceMsg, error)
		Name() string
	}

	Codec interface {
		Decode([]byte) (*DeviceMsg, error)
	}

	DataHandler interface {
		Handle(ctx *transport.Context, msg *DeviceMsg) error
		Name() string
	}

	Gateway interface {
		Start()
	}

	DeviceOperation interface {
		Setting(deviceConfig *managev1.DeviceConfig, params *SettingParams) error
	}
)
